#ifndef POISSON_CONSTRUCT_BASE_H_
#define POISSON_CONSTRUCT_BASE_H_
#include<stdio.h>
#include<stdlib.h>
#include<Algorithm/points_cloud_algorithm.h>
#include <Algorithm/marching_cubes.h>
#ifndef SIGN
#define SIGN(x) ((x>0)?1:((x<0)?-1:0))
#endif

// extern double fx_dot_fx[5];
// extern double fx_dot_Dfx[5];
// extern double fx_dot_DDfx[5];

#ifdef __cplusplus
extern "C" {
#endif

typedef struct Poisson_Grid_Prop {
    int indexs[3];//i,j,k
    double normal_coeff[3],pos[3];
    int num;
    int id;
}Poisson_Grid_Prop;
static inline void poisson_grid_prop_init(Poisson_Grid_Prop* pgp)
{
    if(pgp==NULL)
    {
        return ;
    }
    memset(pgp->indexs,0,sizeof(int)*3);
    memset(pgp->pos,0,sizeof(double)*3);
    memset(pgp->normal_coeff,0,sizeof(double)*3);
    pgp->num=0;
    pgp->id=0;
}
static inline void poisson_grid_prop_free(Poisson_Grid_Prop*pgp)
{
    SAFE_FREE(pgp);
}

typedef struct Poisson_Grid{
    Poisson_Grid_Prop**** pgps;
    double range,width;
    int depth,size;  
    double *solve;
    Node* candidate;

}Poisson_Grid;

static inline void poisson_grid_init(Poisson_Grid*pg)
{
    pg->pgps=NULL;
    pg->range=1.05;pg->width=2*pg->range;
    pg->depth=0;pg->size=0;
    pg->solve=NULL;
    pg->candidate=NULL;
}




void poisson_grid_free(Poisson_Grid*pg);

void poisson_grid_init_with_depth(Poisson_Grid*pg,int depth);
void poisson_grid_init_with_accuracy(Poisson_Grid*pg,int fen);



static inline double poisson_FF(double x)
{
    return (x<=0.5&&x>=-0.5)?(0.75-x*x):( (x<=1.5&&x>=-1.5)?(1.125-1.5*fabs(x)+x*x*0.5):( 0)  );
}
static inline double poisson_DFF(double x)
{
    return (x<=0.5&&x>=-0.5)?(-2*x):( (x<=1.5&&x>=-1.5)?(-1.5*SIGN(x)+x):( 0)  ); 
} 

static inline double poisson_FF_deformation(double* center,double w,double *x )
{
    double p[3]={x[0]-center[0],x[1]-center[1],x[2]-center[2]};
    p[0]/=w;p[1]/=w;p[2]/=w;
    return  poisson_FF(p[0])*poisson_FF(p[1])*poisson_FF(p[2]); 
}


static inline int threeD_index2_id(int i,int j ,int k,int size)
{
    return i*size*size+j*size+k;
}

static inline void id2_threeD_index(int id,int size,int * i,int *j,int *k)
{
    *i=id/(size*size);

    *j=(id-*i*size*size)/size;

    *k=id-*i*size*size-*j*size;  

}

// static 

//void points_cloud_compute_normal_using_clapack(Node* n,KD_Node*kdtree,int num);
double* poisson_compute_b(Poisson_Grid*pg );

double end_poisson_space_fun(double* p,void * tool);

double compute_average_poisson_iso(Poisson_Grid* pg);

Node**** my_marching_cubes_generate_trianglesn(Node* node_v,double iso,int len_grids,double(*fun)(double* ,void*),
    void* tool,Node**tris1);
//法向要插值 
void fill_normal_coeff(Poisson_Grid*pg,Node* node_vertices);


#ifdef __cplusplus
}
#endif


#endif